package com.saver.core.business;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.util.Log;

import com.saver.core.domain.Banco;
import com.saver.core.domain.MensajeTexto;
import com.saver.core.domain.Transaccion;
import com.saver.core.exception.HTTPException;
import com.saver.core.persistence.DBManager;
import com.saver.core.persistence.MensajeTextoInbox;
import com.saver.core.processor.ProcessSMSFactory;
import com.saver.core.processor.ProcessorSMS;
import com.saver.core.processor.TipoToken;
import com.saver.core.processor.Token;

public class TransaccionBusiness {

	private static final String TAG = "TransaccionBusiness";

	private MensajeTextoInbox mensajeTextoInbox;
	
	private TransaccionCache transaccionCache;

	public TransaccionBusiness(Context context, MensajeTextoInbox mensajeTextoInbox) {
        DBManager.initialize(context);
		this.mensajeTextoInbox = mensajeTextoInbox;
		
		transaccionCache = new TransaccionCache(context);
	}
	
	public int migrarABaseDatos(List<Banco> bancos, ProcessSMSFactory processSMSFactory, 
			Short revisado) throws IOException, HTTPException {
		
		Log.d(TAG, "migrarABaseDatos");

		for (Banco banco : bancos) {
			procesarBanco(processSMSFactory, banco, revisado);
		}
		return transaccionCache.finalizar();
	}

	private void procesarBanco(ProcessSMSFactory processSMSFactory, 
			Banco banco, Short revisado) throws IOException, HTTPException {
		
		Log.d(TAG, "procesarBanco: " + banco.getNombre());

		Long max = DBManager.transaccionSQLite().maxFechaXBanco(banco.getId());
		String numero = banco.getNumero();
		Log.i(TAG, "banco: " + banco.getNombre() + " - numero: " + numero);

		List<MensajeTexto> mensajeTextos = mensajeTextoInbox.buscarTodo(numero, max);
		ProcessorSMS processorSMS = processSMSFactory.getProcessSMS(numero);

		for (MensajeTexto mensajeTexto : mensajeTextos) {
			procesarMensajeTexto(processorSMS, banco, mensajeTexto, revisado);
		}
	}
	
	private void procesarMensajeTexto(ProcessorSMS processorSMS, Banco banco, 
			MensajeTexto mensajeTexto, Short revisado) throws IOException, HTTPException {
		
		List<Token> tokens = processorSMS.process(mensajeTexto);
		if (tokens != null) {
			for (Token token : tokens) {
				if (TipoToken.EGRESO.equals(token.getTipoToken())) {
					transaccionCache.agregarToken(token, revisado);
				}
			}
		}
	}

    public Transaccion procesarMensajeTexto(ProcessorSMS processorSMS, 
    		MensajeTexto mensajeTexto, Short revisado) throws IOException, HTTPException {
    	
    	Transaccion transaccion = null;
    	
        List<Token> tokens = processorSMS.process(mensajeTexto);
        if (tokens != null && !tokens.isEmpty()) {
        	Token token = tokens.get(0);
            transaccion = transaccionCache.procesarToken(token, revisado);
        }
        
        return transaccion;
    }
	
/*
	public List<Token> migrarABaseDatos(List<Banco> bancos, ProcessSMSFactory processSMSFactory) throws IOException, HTTPException {
		Log.d(TAG, "migrarABaseDatos");
        List<Token> tokens = new ArrayList<Token>();

		for (Banco banco : bancos) {
            tokens.addAll(procesarBanco(processSMSFactory, banco));
		}
		return tokens;
	}

	private List<Token> procesarBanco(ProcessSMSFactory processSMSFactory, Banco banco) throws IOException, HTTPException {
		Log.d(TAG, "procesarBanco: " + banco.getNombre());
        List<Token> tokens = new ArrayList<Token>();

		Long max = DBManager.transaccionSQLite().maxFechaXBanco(banco.getId());
		String numero = banco.getNumero();
		Log.i(TAG, "banco: " + banco.getNombre() + " - numero: " + numero);

		List<MensajeTexto> mensajeTextos = mensajeTextoInbox.buscarTodo(numero, max);
		ProcessorSMS processorSMS = processSMSFactory.getProcessSMS(numero);

		for (MensajeTexto mensajeTexto : mensajeTextos) {
            tokens.addAll(procesarMensajeTexto(processorSMS, banco, mensajeTexto));
		}
		return tokens;
	}

	private List<Token> procesarMensajeTexto(ProcessorSMS processorSMS, Banco banco, MensajeTexto mensajeTexto) throws IOException, HTTPException {
		List<Token> tokens = processorSMS.process(mensajeTexto);
		if (tokens != null) {
			for (Token token : tokens) {
				if (TipoToken.EGRESO.equals(token.getTipoToken())) {
					Transaccion transaccion = crearTransaccion(banco, token);
                    DBManager.transaccionSQLite().guardar(transaccion);
				}
			}
		}
		return tokens;
	}

    public List<Token> procesarMensajeTexto(ProcessorSMS processorSMS, MensajeTexto mensajeTexto) throws IOException, HTTPException {
        List<Token> tokens = processorSMS.process(mensajeTexto);
        if (tokens != null && !tokens.isEmpty()) {
            for (Token token : tokens) {
                if (TipoToken.EGRESO.equals(token.getTipoToken())) {
                    Banco banco = new Banco();
                    banco.setId(token.getTipoBanco().getId());
                    Transaccion transaccion = crearTransaccion(banco, token);
                    DBManager.transaccionSQLite().guardar(transaccion);
                }
            }
        }
        return tokens;
    }

	private Transaccion crearTransaccion(Banco banco, Token token) throws IOException, HTTPException {
		HashMap<String, String> parametros = new HashMap<String, String>();

		String catEquiv = token.getCategoria();
		Log.d(TAG, "catEquiv: " + catEquiv);
		CategoriaEquiv categoriaEquiv = null;
		if (!Util.esVacio(catEquiv)) {
			categoriaEquiv = DBManager.categoriaEquivSQLite().buscarPorNombre(catEquiv);

			// no existe la categoriaEquiv o no esta clasificado
			if (categoriaEquiv == null || categoriaEquiv.getIdServidor() == null) {
				parametros.put(Constantes.PARAM_SMS_CATEGORIA, catEquiv);
			}
		}

		String estEquiv = token.getEstablecimiento();
		Log.d(TAG, "estEquiv: " + estEquiv);
		EstablecimientoEquiv establecimientoEquiv = null;
		if (!Util.esVacio(estEquiv)) {
			establecimientoEquiv = DBManager.establecimientoEquivSQLite().buscarPorNombre(estEquiv);

			// no existe el establecimientoEquiv o no esta clasificado
			if (establecimientoEquiv == null || establecimientoEquiv.getIdServidor() == null) {
				parametros.put(Constantes.PARAM_SMS_ESTABLECIMIENTO, estEquiv);
			} else {
				Establecimiento establecimiento = DBManager.establecimientoSQLite().buscarPorId(establecimientoEquiv.getIdEstablecimiento());

				// el establecimiento no tiene una categoria
				if (establecimiento == null || establecimiento.getIdCategoria() == null) {
					parametros.put(Constantes.PARAM_SMS_ESTABLECIMIENTO, estEquiv);
				}
			}
		}

		String monEquiv = token.getMoneda();
		Log.d(TAG, "monEquiv: " + monEquiv);
		MonedaEquiv monedaEquiv = null;
		if (!Util.esVacio(monEquiv)) {
			monedaEquiv = DBManager.monedaEquivSQLite().buscarPorNombre(monEquiv);

			// no existe la monedaEquiv o no esta clasificado
			if (monedaEquiv == null || monedaEquiv.getIdServidor() == null) {
				parametros.put(Constantes.PARAM_SMS_MONEDA, monEquiv);
			}
		}

		Transaccion transaccion = new Transaccion();
		// tiene parametros
		if (!parametros.isEmpty()) {
			// tiene salida a internet
			boolean tieneInternet = Util.tieneConexionInternet(context);
			if (tieneInternet) {
				crearInternet(parametros, transaccion, banco, categoriaEquiv, establecimientoEquiv, monedaEquiv, catEquiv, estEquiv, monEquiv);
			} else { // no tiene salida a internet
				crearLocal(parametros, transaccion, categoriaEquiv, establecimientoEquiv, monedaEquiv, catEquiv, estEquiv, monEquiv);
			}
		} else { // no tiene parametros
			if (categoriaEquiv != null) {
				transaccion.setIdCategoria(categoriaEquiv.getId());
				transaccion.setIdCategoriaEquiv(categoriaEquiv.getIdServidor());
			}

			if (establecimientoEquiv != null) {
				transaccion.setIdEstablecimiento(establecimientoEquiv.getId());
				transaccion.setIdEstablecimientoEquiv(establecimientoEquiv.getIdServidor());
			}

			if (monedaEquiv != null) {
				transaccion.setIdMoneda(monedaEquiv.getId());
				transaccion.setIdMonedaEquiv(monedaEquiv.getIdServidor());
			}
		}

		transaccion.setFechaSMS(token.getFechaSMS());
		Long fechaTransaccion = token.getFechaTransaccion();
		if (fechaTransaccion == null) {
			fechaTransaccion = token.getFechaSMS();
		}
		transaccion.setFechaTransaccion(fechaTransaccion);
		transaccion.setIdBanco(token.getTipoBanco().getId());
		transaccion.setMonto(token.getImporte());
		transaccion.setNumero(token.getNumero());
		if (mostrarEnLista) {
			transaccion.setRevisado(Constantes.TRANSACCION_NO_REVISADA);
		} else {
			transaccion.setRevisado(Constantes.TRANSACCION_REVISADA);
		}
		transaccion.setTipo(token.getTipoToken().getId());

		return transaccion;
	}

	private void crearLocal(HashMap<String, String> parametros,
			Transaccion transaccion, CategoriaEquiv categoriaEquiv,
			EstablecimientoEquiv establecimientoEquiv, MonedaEquiv monedaEquiv,
			String catEquiv, String estEquiv, String monEquiv) {
		if (parametros.containsKey(Constantes.PARAM_SMS_CATEGORIA)) {
			if (categoriaEquiv == null) {
				categoriaEquiv = new CategoriaEquiv();
				categoriaEquiv.setNombre(catEquiv);
                DBManager.categoriaEquivSQLite().guardar(categoriaEquiv);
			}
			transaccion.setIdCategoria(categoriaEquiv.getIdCategoria());
			transaccion.setIdCategoriaEquiv(categoriaEquiv.getId());
		}

		if (parametros.containsKey(Constantes.PARAM_SMS_ESTABLECIMIENTO)) {
			if (establecimientoEquiv == null) {
				establecimientoEquiv = new EstablecimientoEquiv();
				establecimientoEquiv.setNombre(estEquiv);
                DBManager.establecimientoEquivSQLite().guardar(establecimientoEquiv);
				// se da prioridad a la categoria del mensaje
			} else if (transaccion.getIdCategoria() == null && establecimientoEquiv.getIdEstablecimiento() != null) {
				Establecimiento establecimiento = DBManager.establecimientoSQLite().buscarPorId(establecimientoEquiv.getIdEstablecimiento());

				if (establecimiento != null && establecimiento.getIdCategoria() != null) {
					transaccion.setIdCategoria(establecimiento.getIdCategoria());
				} else {
					transaccion.setIdCategoria(Constantes.SIN_CATEGORIZAR);
				}
			}
			transaccion.setIdEstablecimiento(establecimientoEquiv.getIdEstablecimiento());
			transaccion.setIdEstablecimientoEquiv(establecimientoEquiv.getId());
		}

        if (transaccion.getIdCategoria() == null) {
            transaccion.setIdCategoria(Constantes.SIN_CATEGORIZAR);
        }

		if (parametros.containsKey(Constantes.PARAM_SMS_MONEDA)) {
			if (monedaEquiv == null) {
				monedaEquiv = new MonedaEquiv();
				monedaEquiv.setNombre(monEquiv);
                DBManager.monedaEquivSQLite().guardar(monedaEquiv);
			}
			transaccion.setIdMoneda(monedaEquiv.getIdMoneda());
			transaccion.setIdMonedaEquiv(monedaEquiv.getId());
		}
	}

	private void crearInternet(HashMap<String, String> parametros,
			Transaccion transaccion, Banco banco,
			CategoriaEquiv categoriaEquiv,
			EstablecimientoEquiv establecimientoEquiv, MonedaEquiv monedaEquiv,
			String catEquiv, String estEquiv, String monEquiv)
			throws IOException, HTTPException {

		parametros.put(Constantes.PARAM_SMS_BANCO, banco.getId().toString());
		SMSRestBean smsRestBean = smsRestService.obtenerDatos(parametros);

		Integer idCategoriaServ = smsRestBean.getIdCategoriaServ();
		Integer idCategoria = smsRestBean.getIdCategoria();
		Integer idEstablecimientoServ = smsRestBean.getIdEstablecimientoServ();
		Integer idEstablecimiento = smsRestBean.getIdEstablecimiento();
		Integer idMonedaServ = smsRestBean.getIdMonedaServ();
		Integer idMoneda = smsRestBean.getIdMoneda();

		if (idCategoria != null) {
			Categoria categoria = DBManager.categoriaSQLite().buscarPorId(idCategoria);
			if (categoria == null) {
				categoria = new Categoria();
				categoria.setId(idCategoria);
				categoria.setNombre(smsRestBean.getNombreCategoria());
                DBManager.categoriaSQLite().guardar(categoria);
			} else {
				categoria.setNombre(smsRestBean.getNombreCategoria());
                DBManager.categoriaSQLite().actualizar(categoria);
			}
		} else {
			idCategoria = Constantes.SIN_CATEGORIZAR;
		}

		if (parametros.containsKey(Constantes.PARAM_SMS_CATEGORIA)) {
			if (categoriaEquiv == null) {
				categoriaEquiv = new CategoriaEquiv();
				categoriaEquiv.setIdCategoria(idCategoria);
				categoriaEquiv.setIdServidor(idCategoriaServ);
				categoriaEquiv.setNombre(catEquiv);
                DBManager.categoriaEquivSQLite().guardar(categoriaEquiv);
			} else {
				categoriaEquiv.setIdCategoria(idCategoria);
				categoriaEquiv.setIdServidor(idCategoriaServ);
				categoriaEquiv.setNombre(catEquiv);
                DBManager.categoriaEquivSQLite().actualizar(categoriaEquiv);
			}
		}

		if (idEstablecimiento != null) {
			Establecimiento establecimiento = DBManager.establecimientoSQLite().buscarPorId(idEstablecimiento);
			if (establecimiento == null) {
				establecimiento = new Establecimiento();
				if (!parametros.containsKey(Constantes.PARAM_SMS_CATEGORIA)) {
					establecimiento.setIdCategoria(idCategoria);
				}
				establecimiento.setIdEstablecimiento(idEstablecimiento);
				establecimiento.setNombre(smsRestBean.getNombreEstablecimiento());
                DBManager.establecimientoSQLite().guardar(establecimiento);

			} else {
				if (!parametros.containsKey(Constantes.PARAM_SMS_CATEGORIA)) {
					establecimiento.setIdCategoria(idCategoria);
				}
				establecimiento.setNombre(smsRestBean.getNombreEstablecimiento());
                DBManager.establecimientoSQLite().actualizar(establecimiento);
			}
		}

		if (parametros.containsKey(Constantes.PARAM_SMS_ESTABLECIMIENTO)) {
			if (establecimientoEquiv == null) {
				establecimientoEquiv = new EstablecimientoEquiv();
				establecimientoEquiv.setIdEstablecimiento(idEstablecimiento);
				establecimientoEquiv.setIdServidor(idEstablecimientoServ);
				establecimientoEquiv.setNombre(estEquiv);
                DBManager.establecimientoEquivSQLite().guardar(establecimientoEquiv);

			} else {
				establecimientoEquiv.setIdEstablecimiento(idEstablecimiento);
				establecimientoEquiv.setIdServidor(idEstablecimientoServ);
				establecimientoEquiv.setNombre(estEquiv);
                DBManager.establecimientoEquivSQLite().actualizar(establecimientoEquiv);
			}
		}

		if (idMoneda != null) {
			Moneda moneda = DBManager.monedaSQLite().buscarPorId(idMoneda);
			if (moneda == null) {
				moneda = new Moneda();
				moneda.setId(idMoneda);
				moneda.setNombre(smsRestBean.getNombreMoneda());
                DBManager.monedaSQLite().guardar(moneda);
			} else {
				moneda.setNombre(smsRestBean.getNombreMoneda());
                DBManager.monedaSQLite().actualizar(moneda);
			}
		}

		if (parametros.containsKey(Constantes.PARAM_SMS_MONEDA)) {
			if (monedaEquiv == null) {
				monedaEquiv = new MonedaEquiv();
				monedaEquiv.setIdMoneda(idMoneda);
				monedaEquiv.setIdServidor(idMonedaServ);
				monedaEquiv.setNombre(monEquiv);
                DBManager.monedaEquivSQLite().guardar(monedaEquiv);
			} else {
				monedaEquiv.setIdMoneda(idMoneda);
				monedaEquiv.setIdServidor(idMonedaServ);
				monedaEquiv.setNombre(monEquiv);
                DBManager.monedaEquivSQLite().actualizar(monedaEquiv);
			}
		}

		transaccion.setIdCategoria(idCategoria);
		if (categoriaEquiv != null) {
			transaccion.setIdCategoriaEquiv(categoriaEquiv.getId());
		}
		transaccion.setIdEstablecimiento(idEstablecimiento);
		if (establecimientoEquiv != null) {
			transaccion.setIdEstablecimientoEquiv(establecimientoEquiv.getId());
		}
		transaccion.setIdMoneda(idMoneda);
		if (monedaEquiv != null) {
			transaccion.setIdMonedaEquiv(monedaEquiv.getId());
		}
	}*/
}
